package FlowGraph.Transformations;

import java.util.*;

import antlr.collections.AST;
import antlr.*;

import FlowGraph.*;
import FlowGraph.Nodes.*;
import JavaGrammar.*;
import SymbolTable.*;
import FlowGraph.StatementInfo.*;
import util.*;

//////////////////////////////////////////////////////////////////////////
//// ForIteratorExtraction
/**

@author Ivan Jeukens
@version v 0.1 12/11/2002
*/
public class ForIteratorExtraction extends Transformation {

    public ForIteratorExtraction(FlowGraph fg) {
        super(fg);
    }

    ///////////////////////////////////////////////////////////////////
    ////                        public  methods                    ////

    // Extrai tudo que esta na iteration do for.
    public void transform(ForBeginNode node) {
        AST iteast = node.getIterator();
        if(iteast != null) {
            iteast = iteast.getFirstChild();  // o elist
            if(iteast != null) {
                _addBBEndLoop(node, iteast.getFirstChild());
                iteast.setFirstChild(null);
            }
        }
    }

    /* Para essa transformacao:
       arg0 = o no ForBegin.
    */
    public void transform(AST n1, AST n2, AST n3, FlowGraphNode node,
            HashMap skipMCTable) {
        _extractForIterator(n1, n2, n3, node, skipMCTable);
    }

    ///////////////////////////////////////////////////////////////////
    ////                        private methods                    ////

    private void _extractForIterator(AST n1, AST n2, AST n3, FlowGraphNode node,
            HashMap skipMCTable) {
        // Nome da variavel de atribuicao
        String varName;
        varName = new String("_tmp" + _flowGraph.getUniqueCount());
        _flowGraph.incrementUniqueCount();

        // Cria a  variavel de atribuicao e uma ST local para o novo no
        LinkedAST top = _createLocalVarAST(varName, null);
        STLocalVariableEntry entry = new STLocalVariableEntry(varName,
             STEntry.LOCAL, top, 0);
        SymbolTable st = new SymbolTable();
        st.putElement(entry.getName(), entry);

        /*CommonToken tok = new CommonToken(JavaTokenTypes.ASSIGN, "=");
        LinkedAST ast = new LinkedAST(tok);

        top.addChild(ast);
        ast.setParent(top);

        tok = new CommonToken(JavaTokenTypes.EXPR, "EXPR");
        LinkedAST expr = new LinkedAST(tok);

        ast.addChild(expr);
        expr.setParent(ast);

        tok = new CommonToken(JavaTokenTypes.METHOD_CALL, "(");
        LinkedAST mcast = new LinkedAST(tok);

        expr.addChild(mcast);
        mcast.setParent(expr);

        ast = Util.dupTree(n2);
        mcast.addChild(ast);
        ast.setParent(mcast);

        ast = Util.dupTree(n3);
        mcast.addChild(ast);
        ast.setParent(mcast);
        */

        BasicBlockNode bb = new BasicBlockNode(top);
        bb.setVarDef(true);
        VarDefStatementInfo vardef = new VarDefStatementInfo(bb, top);
        bb.setStatementInfo(vardef, 0);

        //MethodCallNode mc = new MethodCallNode(top);
        //mc.setVarDef(true);
        //skipMCTable.put(mc, mcast);
        
        // Atualiza a arvore AST.
        n1.setText(varName);
        n1.setType(JavaTokenTypes.IDENT);
        n1.setFirstChild(null);

        // O no com a definicao da variavel
        _addNodeBefore(bb, st, node, true);
        ForBeginNode fbeg = (ForBeginNode) node;
        fbeg.addIteExtractedNode(bb);

        // Inclui a chamada tambem no final (todos os backedges) do loop
        CommonToken tok = new CommonToken(JavaTokenTypes.EXPR, "EXPR");
        LinkedAST ast2 = new LinkedAST(tok);

        tok = new CommonToken(JavaTokenTypes.ASSIGN, "=");
        LinkedAST ast3 = new LinkedAST(tok);

        ast2.addChild(ast3);
        ast3.setParent(ast2);

        tok = new CommonToken(JavaTokenTypes.IDENT, entry.getName());
        LinkedAST ast4 = new LinkedAST(tok);

        ast3.addChild(ast4);
        ast4.setParent(ast3);

        tok = new CommonToken(JavaTokenTypes.METHOD_CALL, "(");
        LinkedAST ast5 = new LinkedAST(tok);

        ast3.addChild(ast5);
        ast5.setParent(ast3);

        LinkedAST ast = Util.dupTree(n2);
        ast5.addChild(ast);
        ast.setParent(ast5);

        ast = Util.dupTree(n3);
        ast5.addChild(ast);
        ast.setParent(ast5);

        MethodCallNode mc2 = new MethodCallNode(ast2);
        mc2.setVarDef(false);
        skipMCTable.put(mc2, ast5);

        _addNodeEndLoop(mc2, node, ast2, ast5, skipMCTable);
    }

    ///////////////////////////////////////////////////////////////////
    ////                      private variables                    ////

}
